package hu.mapro.rollerx.core;

import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;


public class FractalTerrain {

	public float x1 = 0;
	public float x2 = 100;
	public float y1 = 0;
	public float y2 = 0;
	
	public float amplitude = 25;
	public int levels = 6;
	public float denominator = 2.0f;
	
	public FractalTerrain() {
		super();
	}
	
	public int generateFractal(float[] terrainVertices, int terrainVerticeIdx) {
		Vertices vertices = new Vertices(terrainVertices, terrainVerticeIdx);
		generateFractal(vertices);
		return vertices.terrainVerticeIdx;
	}
	
	public void generateFractal(Vertices vertices) {
		new Generator(vertices).generate();
	}

	public int getVertexCount() {
		return (1 << levels) + 1;
	}
	
	class Generator {
		
		Vertices vertices;
		
		public Generator(Vertices vertices) {
			super();
			this.vertices = vertices;
		}

		void generate() {
			fractal(
					x1,
					y1,
					x2,
					y2,
					amplitude,
					levels
			);
			vertices.addVertex(x2, y2);
		}

		void fractal(
				float x1,
				float y1,
				float x2, 
				float y2, 
				float d,
				int n
		) {
			if (n==0) {
				vertices.addVertex(x1, y1);
			} else {
				float xm = (x1+x2)/2;
				float ym = (float) ((y1+y2)/2 + (Math.random()*d*2)-d);
				fractal(x1, y1, xm, ym, d/denominator, n-1);
				fractal(xm, ym, x2, y2, d/denominator, n-1);
			}
		}
		
	}
	
	
	public static class Vertices {
		public float[] terrainVertices;
		public int terrainVerticeIdx;
		
		public Vertices(float[] terrainVertices, int terrainVerticeIdx) {
			super();
			this.terrainVertices = terrainVertices;
			this.terrainVerticeIdx = terrainVerticeIdx;
		}

		public Vertices(int size) {
			terrainVertices = new float[size*2];
			terrainVerticeIdx = 0;
		}
		
		void addVertex(float x, float y) {
			terrainVertices[terrainVerticeIdx++] = x;
			terrainVertices[terrainVerticeIdx++] = y;
		}
		
		public Vector2[] toVector2Array() {
			Vector2[] vecs = new Vector2[terrainVertices.length/2];
			for (int i=0;i<vecs.length;i++) {
				vecs[i] = new Vector2(terrainVertices[i*2], terrainVertices[i*2+1]);
			}
			return vecs;
		}
		
	}

	public void randomizeEndpoints() {
		y1 = MathUtils.random(-amplitude, amplitude);
		y2 = MathUtils.random(-amplitude, amplitude);
	}
	
}
